Skip to content

fix: reject empty TTS text at the schema boundary (Fixes #946)#1303

Open
MushiSenpai wants to merge 1 commit into
fishaudio:mainfrom
MushiSenpai:fix/validate-empty-tts-text-946
Open

fix: reject empty TTS text at the schema boundary (Fixes #946)#1303
MushiSenpai wants to merge 1 commit into
fishaudio:mainfrom
MushiSenpai:fix/validate-empty-tts-text-946

Conversation

@MushiSenpai

Copy link
Copy Markdown

Is this a feature or a BUG fix? BUG fix.

Related issue: Fixes #946

Summary

POST /v1/tts returns an HTTP 500 with a JSON error body when text is empty.
A client that streams the response then writes that JSON error into a .wav file.

Root cause is a schema asymmetry in fish_speech/utils/schema.py:

  • ServeTTSRequest.text was an unconstrained str, so an empty string passes
    validation and flows into synthesis.
  • Empty text yields zero audio segments, which TTSInferenceEngine.inference
    reports as an error and tools/server/inference.py re-raises as
    HTTPException(INTERNAL_SERVER_ERROR) → the 500 reported in baize.exceptions.HTTPException: (500, "'No audio generated, please check the input text.'") #946
    ("No audio generated, please check the input text.").
  • The sibling model AddReferenceRequest.text already constrains
    min_length=1, so the asymmetry is the bug.

The fix

Constrain ServeTTSRequest.text the same way, so empty input is rejected with a
clean 4xx validation error at the request boundary — before any model work:

# fish_speech/utils/schema.py
class ServeTTSRequest(BaseModel):
-    text: str
+    text: str = Field(..., min_length=1)

One line, no behavior change for valid input. Matches the existing min_length=1
on AddReferenceRequest.text and the Field(...) constraint style already used on
ServeTTSRequest (top_p, temperature, repetition_penalty).

Validation

The change is pure pydantic validation (no model weights needed). Importing the
model and constructing it:

Input Before After
text="" accepted → empty segments → HTTP 500 ValidationError (clean 4xx)
text="hello" accepted accepted (unchanged)

Scope

This fixes the empty-string trigger at the schema boundary. The broader
"no segments generated → 500" path (e.g. other degenerate inputs) is a separate,
larger change in tools/server/inference.py and is intentionally out of scope here.


Disclosure: this fix was drafted with AI assistance (Claude) and reviewed, tested,
and submitted by me. The commit carries a Co-Authored-By trailer.

ServeTTSRequest.text was an unconstrained `str`, so empty text reached synthesis,
produced zero audio segments, and surfaced as an HTTP 500 with a JSON error body
(issue fishaudio#946) which a streaming client then writes as a .wav. The sibling
AddReferenceRequest.text already constrains min_length=1; apply the same to
ServeTTSRequest.text so empty input is rejected with a clean 4xx at the boundary.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

baize.exceptions.HTTPException: (500, "'No audio generated, please check the input text.'")

1 participant